home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 2 / MacMania 2.toast / Demo's / Tools&Utilities / Programming / SPIM Folder / Sources / run.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-03  |  29.0 KB  |  1,396 lines  |  [TEXT/ttxt]

  1. /* SPIM S20 MIPS simulator.
  2.    Execute SPIM instructions.
  3.    Copyright (C) 1990 by James Larus (larus@cs.wisc.edu).
  4.  
  5.    SPIM is free software; you can redistribute it and/or modify it
  6.    under the terms of the GNU General Public License as published by the
  7.    Free Software Foundation; either version 1, or (at your option) any
  8.    later version.
  9.  
  10.    SPIM is distributed in the hope that it will be useful, but WITHOUT
  11.    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12.    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13.    for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with GNU CC; see the file COPYING.  If not, write to James R.
  17.    Larus, Computer Sciences Department, University of Wisconsin--Madison,
  18.    1210 West Dayton Street, Madison, WI 53706, USA or to the Free
  19.    Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21.  
  22. /* $Header: /var/home/cs354/.spim/RCS/run.c,v 1.4 1992/10/12 11:34:13 cs354 Exp $
  23. */
  24.  
  25.  
  26. #ifdef mips
  27. #define _IEEE 1
  28. #include <nan.h>
  29. #include <syscall.h>
  30. #include "mips-syscall.h"
  31. #else
  32. #define NaN(X) 0
  33. #endif
  34.  
  35. #include <math.h>
  36. #include <stdio.h>
  37. #ifndef WIN32
  38. #ifndef MACINTOSH
  39. #include <X11/Intrinsic.h>
  40. #include <X11/StringDefs.h>
  41. #endif
  42. #endif
  43.  
  44. #include "spim.h"
  45. #include "inst.h"
  46. #include "mem.h"
  47. #include "reg.h"
  48. #include "sym_tbl.h"
  49. #ifdef WIN32
  50. #include "spim-sys.h"
  51. #include "y_tab.h"
  52. extern int IntCheck();
  53. #else
  54. #ifdef MACINTOSH
  55. #include "spim-sys.h"
  56. #include "y_tab.h"
  57. #else
  58. #include "spim-syscall.h"
  59. #include "y.tab.h"
  60. #endif
  61. #endif
  62.  
  63. /* Exported functions: */
  64.  
  65. int run_spim (mem_addr initial_PC, register int steps, int display);
  66.  
  67.  
  68. /* Local functions: */
  69.  
  70. static void long_multiply (reg_word v1, reg_word v2);
  71.  
  72.  
  73. /* Imported variables: */
  74.  
  75. extern char *ex_file_name;
  76. extern int errno;
  77. extern int errno_addr;
  78. int program_break;
  79.  
  80. /* Delayed branch instructions set delay_PC to the address of their
  81.    target and then execute another instruction.
  82.  
  83.    Note that we take advantage of the MIPS architecture, which leaves
  84.    undefined the result of executing a delayed instruction in a delay
  85.    slot.  Here we just execute the second branch. */
  86.  
  87.  
  88. #define DELAYED_UPDATE(A, D) {if (delayed_addr1 != NULL)        \
  89.                 fatal_error("Two calls to DELAYED_UPDATE\n");\
  90.                 delayed_addr1 = A; delayed_value1 = D;}
  91.  
  92.  
  93. #define DO_DELAYED_UPDATE() if (bare_machine)                \
  94.                    {                    \
  95.                  /* Check for delayed updates */    \
  96.                  if (delayed_addr2 != NULL)        \
  97.                    *delayed_addr2 = delayed_value2;    \
  98.                  delayed_addr2 = delayed_addr1;        \
  99.                  delayed_value2 = delayed_value1;    \
  100.                  delayed_addr1 = NULL;            \
  101.                    }
  102.  
  103. #define SIGN_BIT(X) ((X) & 0x80000000)
  104.  
  105. #define ARITH_OVFL(RESULT, OP1, OP2) (SIGN_BIT (OP1) == SIGN_BIT (OP2) \
  106.                       && SIGN_BIT (OP1) != SIGN_BIT (RESULT))
  107.  
  108. #define LOAD_INST(OP, ADDR, DEST_A, MASK)                \
  109.                  {reg_word tmp = 0;            \
  110.                    OP (tmp, (ADDR));            \
  111.                    tmp &= (MASK);            \
  112.                    if (bare_machine)            \
  113.                      {                    \
  114.                      DELAYED_UPDATE ((DEST_A), tmp);    \
  115.                      run_spim (PC+BYTES_PER_WORD, 1, display);\
  116.                      PC -= BYTES_PER_WORD;        \
  117.                      }                    \
  118.                    else                    \
  119.                      *(DEST_A) = tmp;            \
  120.                    }
  121.  
  122. #define BRANCH_INST(TEST, VALUE) {mem_addr delay_PC = -1;        \
  123.                   if (TEST)                \
  124.                     delay_PC = VALUE;            \
  125.                   if (bare_machine)            \
  126.                      run_spim (PC+BYTES_PER_WORD, 1, display);\
  127.                   if (delay_PC != -1)            \
  128.                     PC = delay_PC;            \
  129.                  }
  130.  
  131.  
  132. #define JUMP_INST(VALUE) {if (bare_machine)                \
  133.                 run_spim (PC+BYTES_PER_WORD, 1, display);    \
  134.               PC = VALUE - BYTES_PER_WORD;            \
  135.               }
  136.  
  137.  
  138.  
  139. /* Run a program stored at PC for N steps.  If display FLAG is
  140.    non-zero, print each instruction before it executes.     Return non-zero
  141.    if program's execution can continue. */
  142.  
  143. int run_spim (mem_addr initial_PC, register int steps, int display)
  144. {
  145.   static reg_word *delayed_addr1 = NULL, delayed_value1;
  146.   static reg_word *delayed_addr2 = NULL, delayed_value2;
  147.   register instruction *inst;
  148.  
  149.  
  150.   PC = initial_PC;
  151.   while (steps -- != 0) {
  152.  
  153. #ifdef WIN32
  154.  
  155.     /* look at the message queue for the "running..." dialog box; if
  156.      * the interrupt button has been pressed, RunPeek() is true */
  157.     
  158.     if(IntCheck())
  159.       control_c_seen();
  160. #endif
  161.  
  162. #ifdef MACINTOSH
  163.  
  164.       /* Good idea, Scott! Let's do the same damn thing on the Mac. */
  165.       /* Of course, the implementation is totally different.... */
  166.  
  167.       if ( IntCheck() )
  168.         control_c_seen();
  169.  
  170. #endif
  171.  
  172.       R [0] = 0;        /* Maintain invariant value */
  173.  
  174.       READ_MEM_INST (inst, PC);
  175.  
  176.       if (exception_occurred)
  177.     {
  178.       exception_occurred = 0;
  179.       EPC = PC & 0xfffffffc; /* Round down */
  180.       PC = EXCEPTION_ADDR;
  181.       continue;
  182.     }
  183.       else if (inst == NULL) {
  184.         sprintf(mess_buff,
  185.           "Attempt to execute non-instruction at 0x%08x\n", PC);
  186.     run_error (mess_buff);
  187.       }
  188.       else if (EXPR (inst) != NULL
  189.            && EXPR (inst)->symbol != NULL
  190.            && EXPR (inst)->symbol->addr == 0)
  191.     {
  192.       sprintf(mess_buff,
  193.         "Instruction references undefined symbol at 0x%08x\n", PC);
  194.       error (mess_buff);
  195.       print_inst (PC);
  196.       run_error ("");
  197.     }
  198.  
  199.       if (display)
  200.     print_inst (PC);
  201.  
  202. #ifdef TEST_ASM
  203.       test_assembly (inst);
  204. #endif
  205.  
  206.       DO_DELAYED_UPDATE ();
  207.  
  208.       switch (OPCODE (inst))
  209.     {
  210.     case Y_ADD_OP:
  211.       {
  212.         register reg_word vs = R[RS (inst)], vt = R[RT (inst)];
  213.         register reg_word sum = vs + vt;
  214.  
  215.         if (ARITH_OVFL (sum, vs, vt))
  216.           RAISE_EXCEPTION (OVF_EXCPT, break);
  217.         R[RD (inst)] = sum;
  218.         break;
  219.       }
  220.  
  221.     case Y_ADDI_OP:
  222.       {
  223.         register reg_word vs = R[RS (inst)], imm = (short) IMM (inst);
  224.         register reg_word sum = vs + imm;
  225.  
  226.         if (ARITH_OVFL (sum, vs, imm))
  227.           RAISE_EXCEPTION (OVF_EXCPT, break);
  228.         R[RT (inst)] = sum;
  229.         break;
  230.       }
  231.     case Y_ADDIU_OP:
  232.       R[RT (inst)] = R[RS (inst)] + (short) IMM (inst);
  233.       break;
  234.  
  235.     case Y_ADDU_OP:
  236.       R[RD (inst)] = R[RS (inst)] + R[RT (inst)];
  237.       break;
  238.  
  239.     case Y_AND_OP:
  240.       R[RD (inst)] = R[RS (inst)] & R[RT (inst)];
  241.       break;
  242.  
  243.     case Y_ANDI_OP:
  244.       R[RT (inst)] = R[RS (inst)] & (0xffff & IMM (inst));
  245.       break;
  246.  
  247.     case Y_BC0F_OP:
  248.     case Y_BC2F_OP:
  249.     case Y_BC3F_OP:
  250.       BRANCH_INST (CpCond[OPCODE (inst) - Y_BC0F_OP] == 0,
  251.                PC + (SIGN_EX (IOFFSET (inst)) << 2));
  252.       break;
  253.  
  254.     case Y_BC0T_OP:
  255.     case Y_BC2T_OP:
  256.     case Y_BC3T_OP:
  257.       BRANCH_INST (CpCond[OPCODE (inst) - Y_BC0T_OP] != 0,
  258.                PC + (SIGN_EX (IOFFSET (inst)) << 2));
  259.       break;
  260.  
  261.     case Y_BEQ_OP:
  262.       BRANCH_INST (R[RS (inst)] == R[RT (inst)],
  263.                PC + (SIGN_EX (IOFFSET (inst)) << 2));
  264.       break;
  265.  
  266.     case Y_BGEZ_OP:
  267.       BRANCH_INST (SIGN_BIT (R[RS (inst)]) == 0,
  268.                PC + (SIGN_EX (IOFFSET (inst)) << 2));
  269.       break;
  270.  
  271.     case Y_BGEZAL_OP:
  272.       if (bare_machine)
  273.         R[31] = PC + 2 * BYTES_PER_WORD;
  274.       else
  275.         R[31] = PC + BYTES_PER_WORD;
  276.       BRANCH_INST (SIGN_BIT (R[RS (inst)]) == 0,
  277.                PC + (SIGN_EX (IOFFSET (inst)) << 2));
  278.       break;
  279.  
  280.     case Y_BGTZ_OP:
  281.       BRANCH_INST (R[RS (inst)] != 0 && SIGN_BIT (R[RS (inst)]) == 0,
  282.                PC + (SIGN_EX (IOFFSET (inst)) << 2));
  283.       break;
  284.  
  285.     case Y_BLEZ_OP:
  286.       BRANCH_INST (R[RS (inst)] == 0 || SIGN_BIT (R[RS (inst)]) != 0,
  287.                PC + (SIGN_EX (IOFFSET (inst)) << 2));
  288.       break;
  289.  
  290.     case Y_BLTZ_OP:
  291.       BRANCH_INST (SIGN_BIT (R[RS (inst)]) != 0,
  292.                PC + (SIGN_EX (IOFFSET (inst)) << 2));
  293.       break;
  294.  
  295.     case Y_BLTZAL_OP:
  296.       if (bare_machine)
  297.         R[31] = PC + 2 * BYTES_PER_WORD;
  298.       else
  299.         R[31] = PC + BYTES_PER_WORD;
  300.       BRANCH_INST (SIGN_BIT (R[RS (inst)]) != 0,
  301.                PC + (SIGN_EX (IOFFSET (inst)) << 2));
  302.       break;
  303.  
  304.     case Y_BNE_OP:
  305.       BRANCH_INST (R[RS (inst)] != R[RT (inst)],
  306.                PC + (SIGN_EX (IOFFSET (inst)) << 2));
  307.       break;
  308.  
  309.     case Y_BREAK_OP:
  310.       if (RD (inst) == 1)
  311.         RAISE_EXCEPTION (BKPT_EXCPT, return (1)) /* Debugger breakpoint */
  312.       else
  313.         RAISE_EXCEPTION (BKPT_EXCPT, break);
  314.  
  315.     case Y_CFC0_OP:
  316.     case Y_CFC2_OP:
  317.     case Y_CFC3_OP:
  318.       R[RT (inst)] = CCR [OPCODE (inst) - Y_CFC0_OP] [RD (inst)];
  319.       break;
  320.  
  321.     case Y_COP0_OP:
  322.     case Y_COP1_OP:
  323.     case Y_COP2_OP:
  324.     case Y_COP3_OP:
  325.       CCR [OPCODE (inst) - Y_COP0_OP] [RD (inst)] = R[RT (inst)];
  326.       break;
  327.  
  328.     case Y_CTC0_OP:
  329.     case Y_CTC2_OP:
  330.     case Y_CTC3_OP:
  331.       CCR [OPCODE (inst) - Y_CTC0_OP] [RD (inst)] = R[RT (inst)];
  332.       break;
  333.  
  334.     case Y_DIV_OP:
  335.       if (R[RT (inst)] != 0)
  336.         {
  337.           LO = (long) R[RS (inst)] / (long) R[RT (inst)];
  338.           HI = (long) R[RS (inst)] % (long) R[RT (inst)];
  339.         }
  340.       break;
  341.  
  342.     case Y_DIVU_OP:
  343.       if (R[RT (inst)] != 0)
  344.         {
  345.           LO = (unsigned long) R[RS (inst)] / (unsigned long) R[RT (inst)];
  346.           HI = (unsigned long) R[RS (inst)] % (unsigned long) R[RT (inst)];
  347.         }
  348.       break;
  349.  
  350.     case Y_J_OP:
  351.       JUMP_INST (((PC & 0xf0000000) | TARGET (inst) << 2));
  352.       break;
  353.  
  354.     case Y_JAL_OP:
  355.       if (bare_machine)
  356.         R[31] = PC + 2 * BYTES_PER_WORD;
  357.       else
  358.         R[31] = PC + BYTES_PER_WORD;
  359.       JUMP_INST (((PC & 0xf0000000) | (TARGET (inst) << 2)));
  360.       break;
  361.  
  362.     case Y_JALR_OP:
  363.       {
  364.         mem_addr tmp = R[RS (inst)];
  365.  
  366.         if (bare_machine)
  367.           R[RD (inst)] = PC + 2 * BYTES_PER_WORD;
  368.         else
  369.           R[RD (inst)] = PC + BYTES_PER_WORD;
  370.         JUMP_INST (tmp);
  371.       }
  372.       break;
  373.  
  374.     case Y_JR_OP:
  375.       {
  376.         mem_addr tmp = R[RS (inst)];
  377.  
  378.         JUMP_INST (tmp);
  379.       }
  380.       break;
  381.  
  382.     case Y_LB_OP:
  383.       LOAD_INST (READ_MEM_BYTE, R[BASE (inst)] + IOFFSET (inst),
  384.              &R[RT (inst)], 0xffffffff);
  385.         break;
  386.  
  387.     case Y_LBU_OP:
  388.       LOAD_INST (READ_MEM_BYTE, R[BASE (inst)] + IOFFSET (inst),
  389.              &R[RT (inst)], 0xff);
  390.       break;
  391.  
  392.     case Y_LH_OP:
  393.       LOAD_INST (READ_MEM_HALF, R[BASE (inst)] + IOFFSET (inst),
  394.              &R[RT (inst)], 0xffffffff);
  395.         break;
  396.  
  397.     case Y_LHU_OP:
  398.       LOAD_INST (READ_MEM_HALF, R[BASE (inst)] + IOFFSET (inst),
  399.              &R[RT (inst)], 0xffff);
  400.       break;
  401.  
  402.     case Y_LUI_OP:
  403.       R[RT (inst)] = (IMM (inst) << 16) & 0xffff0000;
  404.       break;
  405.  
  406.     case Y_LW_OP:
  407.       LOAD_INST (READ_MEM_WORD, R[BASE (inst)] + IOFFSET (inst),
  408.              &R[RT (inst)], 0xffffffff);
  409.         break;
  410.  
  411.     case Y_LWC0_OP:
  412.     case Y_LWC2_OP:
  413.     case Y_LWC3_OP:
  414.       LOAD_INST (READ_MEM_WORD, R[BASE (inst)] + IOFFSET (inst),
  415.              &CPR [OPCODE (inst) - Y_LWC0_OP] [RT (inst)], 0xffffffff);
  416.         break;
  417.  
  418.     case Y_LWL_OP:
  419.       {
  420.         register mem_addr addr = R[BASE (inst)] + IOFFSET (inst);
  421.         reg_word word;    /* Can't be register */
  422.         register int byte = addr & 0x3;
  423.         reg_word reg_val = R[RT (inst)];
  424.  
  425.         LOAD_INST (READ_MEM_WORD, addr & 0xfffffffc, &word, 0xffffffff);
  426.         DO_DELAYED_UPDATE ();
  427.  
  428.         if ((!exception_occurred) || ((Cause >> 2) > LAST_REAL_EXCEPT))
  429. #ifdef BIGENDIAN
  430.           switch (byte)
  431.         {
  432.         case 0:
  433.           R[RT (inst)] = word;
  434.           break;
  435.  
  436.         case 1:
  437.           R[RT (inst)] = (word & 0xffffff) << 8 | (reg_val & 0xff);
  438.           break;
  439.  
  440.         case 2:
  441.           R[RT (inst)] = (word & 0xffff) << 16 | (reg_val & 0xffff);
  442.           break;
  443.  
  444.         case 3:
  445.           R[RT (inst)] = (word & 0xff) << 24 | (reg_val & 0xffffff);
  446.           break;
  447.         }
  448. #else
  449.         switch (byte)
  450.           {
  451.           case 0:
  452.         R[RT (inst)] = (word & 0xff) << 24 | (reg_val & 0xffffff);
  453.         break;
  454.  
  455.           case 1:
  456.         R[RT (inst)] = (word & 0xffff) << 16 | (reg_val & 0xffff);
  457.         break;
  458.  
  459.           case 2:
  460.         R[RT (inst)] = (word & 0xffffff) << 8 | (reg_val & 0xff);
  461.         break;
  462.  
  463.           case 3:
  464.         R[RT (inst)] = word;
  465.         break;
  466.           }
  467. #endif
  468.         break;
  469.       }
  470.  
  471.     case Y_LWR_OP:
  472.       {
  473.         register mem_addr addr = R[BASE (inst)] + IOFFSET (inst);
  474.         reg_word word;    /* Can't be register */
  475.         register int byte = addr & 0x3;
  476.         reg_word reg_val = R[RT (inst)];
  477.  
  478.         LOAD_INST (READ_MEM_WORD, addr & 0xfffffffc, &word, 0xffffffff);
  479.         DO_DELAYED_UPDATE ();
  480.  
  481.         if ((!exception_occurred) || ((Cause >> 2) > LAST_REAL_EXCEPT))
  482. #ifdef BIGENDIAN
  483.           switch (byte)
  484.         {
  485.         case 0:
  486.           R[RT (inst)] = (reg_val & 0xffffff00)
  487.             | ((word & 0xff000000) >> 24);
  488.           break;
  489.  
  490.         case 1:
  491.           R[RT (inst)] = (reg_val & 0xffff0000)
  492.             | ((word & 0xffff0000) >> 16);
  493.           break;
  494.  
  495.         case 2:
  496.           R[RT (inst)] = (reg_val & 0xff000000)
  497.             | ((word & 0xffffff00) >> 8);
  498.           break;
  499.  
  500.         case 3:
  501.           R[RT (inst)] = word;
  502.           break;
  503.         }
  504. #else
  505.         switch (byte)
  506.           {
  507.         /* NB: The description of the little-endian case in Kane is
  508.            totally wrong. */
  509.           case 0:        /* 3 in book */
  510.         R[RT (inst)] = reg_val;
  511.         break;
  512.  
  513.           case 1:        /* 0 in book */
  514.         R[RT (inst)] = (reg_val & 0xff000000)
  515.           | ((word & 0xffffff00) >> 8);
  516.         break;
  517.  
  518.           case 2:        /* 1 in book */
  519.         R[RT (inst)] = (reg_val & 0xffff0000)
  520.           | ((word & 0xffff0000) >> 16);
  521.         break;
  522.  
  523.           case 3:        /* 2 in book */
  524.         R[RT (inst)] = (reg_val & 0xffffff00)
  525.           | ((word & 0xff000000) >> 24);
  526.         break;
  527.           }
  528. #endif
  529.         break;
  530.       }
  531.  
  532.     case Y_MFC0_OP:
  533.     case Y_MFC2_OP:
  534.     case Y_MFC3_OP:
  535.       R[RT (inst)] = CPR [OPCODE (inst) - Y_MFC0_OP] [RD (inst)];
  536.       break;
  537.  
  538.     case Y_MFHI_OP:
  539.       R[RD (inst)] = HI;
  540.       break;
  541.  
  542.     case Y_MFLO_OP:
  543.       R[RD (inst)] = LO;
  544.       break;
  545.  
  546.     case Y_MTC0_OP:
  547.     case Y_MTC2_OP:
  548.     case Y_MTC3_OP:
  549.       CPR [OPCODE (inst) - Y_MTC0_OP] [RD (inst)] = R[RT (inst)];
  550.       break;
  551.  
  552.     case Y_MTHI_OP:
  553.       HI = R[RS (inst)];
  554.       break;
  555.  
  556.     case Y_MTLO_OP:
  557.       LO = R[RS (inst)];
  558.       break;
  559.  
  560.     case Y_MULT_OP:
  561.       {
  562.         reg_word v1 = R[RS (inst)], v2 = R[RT (inst)];
  563.         int neg_sign = 0;
  564.  
  565.         if (v1 < 0)
  566.           v1 = - v1, neg_sign = 1;
  567.         if (v2 < 0)
  568.           v2 = - v2, neg_sign = ! neg_sign;
  569.  
  570.         long_multiply (v1, v2);
  571.         if (neg_sign)
  572.           {
  573.         LO = ~ LO;
  574.         HI = ~ HI;
  575.         LO += 1;
  576.         if (LO == 0)
  577.           HI += 1;
  578.           }
  579.       }
  580.       break;
  581.  
  582.     case Y_MULTU_OP:
  583.       long_multiply (R [RS (inst)], R[RT (inst)]);
  584.       break;
  585.  
  586.     case Y_NOR_OP:
  587.       R[RD (inst)] = ~ (R[RS (inst)] | R[RT (inst)]);
  588.       break;
  589.  
  590.     case Y_OR_OP:
  591.       R[RD (inst)] = R[RS (inst)] | R[RT (inst)];
  592.       break;
  593.  
  594.     case Y_ORI_OP:
  595.       R[RT (inst)] = R[RS (inst)] | (0xffff & IMM (inst));
  596.       break;
  597.  
  598.     case Y_RFE_OP:
  599.       Status_Reg = (Status_Reg & 0xfffffff0) | ((Status_Reg & 0x3c) >> 2);
  600.       break;
  601.  
  602.     case Y_SB_OP:
  603.       SET_MEM_BYTE (R[BASE (inst)] + IOFFSET (inst), R[RT (inst)]);
  604.       break;
  605.  
  606.     case Y_SH_OP:
  607.       SET_MEM_HALF (R[BASE (inst)] + IOFFSET (inst), R[RT (inst)]);
  608.       break;
  609.  
  610.     case Y_SLL_OP:
  611.       {
  612.         int shamt = SHAMT (inst);
  613.  
  614.         if (shamt >= 0 && shamt < 32)
  615.           R[RD (inst)] = R[RT (inst)] << shamt;
  616.         else
  617.           R[RD (inst)] = R[RT (inst)];
  618.         break;
  619.       }
  620.  
  621.     case Y_SLLV_OP:
  622.       {
  623.         int shamt = (R[RS (inst)] & 0x1f);
  624.  
  625.         if (shamt >= 0 && shamt < 32)
  626.           R[RD (inst)] = R[RT (inst)] << shamt;
  627.         else
  628.           R[RD (inst)] = R[RT (inst)];
  629.         break;
  630.       }
  631.  
  632.     case Y_SLT_OP:
  633.       if (R[RS (inst)] < R[RT (inst)])
  634.         R[RD (inst)] = 1;
  635.       else
  636.         R[RD (inst)] = 0;
  637.       break;
  638.  
  639.     case Y_SLTI_OP:
  640.       if (R[RS (inst)] < (short) IMM (inst))
  641.         R[RT (inst)] = 1;
  642.       else
  643.         R[RT (inst)] = 0;
  644.       break;
  645.  
  646.     case Y_SLTIU_OP:
  647.       {
  648.         int x = (short) IMM (inst);
  649.  
  650.         if ((unsigned long) R[RS (inst)] < (unsigned long) x)
  651.           R[RT (inst)] = 1;
  652.         else
  653.           R[RT (inst)] = 0;
  654.         break;
  655.       }
  656.  
  657.     case Y_SLTU_OP:
  658.       if ((unsigned long) R[RS (inst)] < (unsigned long) R[RT (inst)])
  659.         R[RD (inst)] = 1;
  660.       else
  661.         R[RD (inst)] = 0;
  662.       break;
  663.  
  664.     case Y_SRA_OP:
  665.       {
  666.         int shamt = SHAMT (inst);
  667.         long val = R[RT (inst)];
  668.  
  669.         if (shamt >= 0 && shamt < 32)
  670.           R[RD (inst)] = val >> shamt;
  671.         else
  672.           R[RD (inst)] = val;
  673.         break;
  674.       }
  675.  
  676.     case Y_SRAV_OP:
  677.       {
  678.         int shamt = R[RS (inst)] & 0x1f;
  679.         long val = R[RT (inst)];
  680.  
  681.         if (shamt >= 0 && shamt < 32)
  682.           R[RD (inst)] = val >> shamt;
  683.         else
  684.           R[RD (inst)] = val;
  685.         break;
  686.       }
  687.  
  688.     case Y_SRL_OP:
  689.       {
  690.         int shamt = SHAMT (inst);
  691.         unsigned long val = R[RT (inst)];
  692.  
  693.         if (shamt >= 0 && shamt < 32)
  694.           R[RD (inst)] = val >> shamt;
  695.         else
  696.           R[RD (inst)] = val;
  697.         break;
  698.       }
  699.  
  700.     case Y_SRLV_OP:
  701.       {
  702.         int shamt = R[RS (inst)] & 0x1f;
  703.         unsigned long val = R[RT (inst)];
  704.  
  705.         if (shamt >= 0 && shamt < 32)
  706.           R[RD (inst)] = val >> shamt;
  707.         else
  708.           R[RD (inst)] = val;
  709.         break;
  710.       }
  711.  
  712.     case Y_SUB_OP:
  713.       {
  714.         register reg_word vs = R[RS (inst)], vt = R[RT (inst)];
  715.         register reg_word diff = vs - vt;
  716.  
  717.         if (SIGN_BIT (vs) != SIGN_BIT (vt)
  718.         && SIGN_BIT (vs) != SIGN_BIT (diff))
  719.           RAISE_EXCEPTION (OVF_EXCPT, break);
  720.         R[RD (inst)] = diff;
  721.         break;
  722.       }
  723.  
  724.     case Y_SUBU_OP:
  725.       R[RD (inst)] = (unsigned long) R[RS (inst)]
  726.         - (unsigned long) R[RT (inst)];
  727.       break;
  728.  
  729.     case Y_SW_OP:
  730.       SET_MEM_WORD (R[BASE (inst)] + IOFFSET (inst), R[RT (inst)]);
  731.       break;
  732.  
  733.     case Y_SWC0_OP:
  734.     case Y_SWC2_OP:
  735.     case Y_SWC3_OP:
  736.       SET_MEM_WORD (R[BASE (inst)] + IOFFSET (inst),
  737.             CPR [OPCODE (inst) - Y_SWC0_OP] [RT (inst)]);
  738.       break;
  739.  
  740.     case Y_SWL_OP:
  741.       {
  742.         register mem_addr addr = R[BASE (inst)] + IOFFSET (inst);
  743.         mem_word data;
  744.         reg_word reg = R[RT (inst)];
  745.         register int byte = addr & 0x3;
  746.  
  747.         READ_MEM_WORD (data, (addr & 0xfffffffc));
  748. #ifdef BIGENDIAN
  749.         switch (byte)
  750.           {
  751.           case 0:
  752.         data = reg;
  753.         break;
  754.  
  755.           case 1:
  756.         data = (data & 0xff000000) | (reg >> 8 & 0xffffff);
  757.         break;
  758.  
  759.           case 2:
  760.         data = (data & 0xffff0000) | (reg >> 16 & 0xffff);
  761.         break;
  762.  
  763.           case 3:
  764.         data = (data & 0xffffff00) | (reg >> 24 & 0xff);
  765.         break;
  766.           }
  767. #else
  768.         switch (byte)
  769.           {
  770.           case 0:
  771.         data = (data & 0xffffff00) | (reg >> 24 & 0xff);
  772.         break;
  773.  
  774.           case 1:
  775.         data = (data & 0xffff0000) | (reg >> 16 & 0xffff);
  776.         break;
  777.  
  778.           case 2:
  779.         data = (data & 0xff000000) | (reg >> 8 & 0xffffff);
  780.         break;
  781.  
  782.           case 3:
  783.         data = reg;
  784.         break;
  785.           }
  786. #endif
  787.         SET_MEM_WORD (addr & 0xfffffffc, data);
  788.         break;
  789.       }
  790.  
  791.     case Y_SWR_OP:
  792.       {
  793.         register mem_addr addr = R[BASE (inst)] + IOFFSET (inst);
  794.         mem_word data;
  795.         reg_word reg = R[RT (inst)];
  796.         register int byte = addr & 0x3;
  797.  
  798.         READ_MEM_WORD (data, (addr & 0xfffffffc));
  799. #ifdef BIGENDIAN
  800.         switch (byte)
  801.           {
  802.           case 0:
  803.         data = ((reg << 24) & 0xff000000) | (data & 0xffffff);
  804.         break;
  805.  
  806.           case 1:
  807.         data = ((reg << 16) & 0xffff0000) | (data & 0xffff);
  808.         break;
  809.  
  810.           case 2:
  811.         data = ((reg << 8) & 0xffffff00) | (data & 0xff) ;
  812.         break;
  813.  
  814.           case 3:
  815.         data = reg;
  816.         break;
  817.           }
  818. #else
  819.         switch (byte)
  820.           {
  821.           case 0:
  822.         data = reg;
  823.         break;
  824.  
  825.           case 1:
  826.         data = ((reg << 8) & 0xffffff00) | (data & 0xff) ;
  827.         break;
  828.  
  829.           case 2:
  830.         data = ((reg << 16) & 0xffff0000) | (data & 0xffff);
  831.         break;
  832.  
  833.           case 3:
  834.         data = ((reg << 24) & 0xff000000) | (data & 0xffffff);
  835.         break;
  836.           }
  837. #endif
  838.         SET_MEM_WORD (addr & 0xfffffffc, data);
  839.         break;
  840.       }
  841.  
  842.     case Y_SYSCALL_OP:
  843. #ifdef mips
  844.       if (!source_file)
  845.         {
  846.           /* Use actual MIPS system calls after translating arguments
  847.            from simulated memory to actual memory.*/
  848.           if (R[REG_V0] > MAX_SYSCALL)
  849.         {
  850.           run_error(sprintf(mess_buff,
  851.             "Illegal system call: %d\n", R[REG_V0]));
  852.           break;
  853.         }
  854.           switch(syscall_table[R[REG_V0]].syscall_type)
  855.         {
  856.         case BAD_SYSCALL:
  857.           run_error (sprintf(mess_buff,
  858.             "Unknown system call: %d\n", R[REG_V0]));
  859.           break;
  860.  
  861.         case UNIX_SYSCALL:
  862.           {
  863.             int arg0, arg1, arg2, arg3;
  864.  
  865.             arg0 = SYSCALL_ARG(arg0, REG_A0);
  866.             arg1 = SYSCALL_ARG(arg1, REG_A1);
  867.             arg2 = SYSCALL_ARG(arg2, REG_A2);
  868.             arg3 = SYSCALL_ARG(arg3, REG_A3);
  869.  
  870.             R[REG_RES] = syscall(R[REG_V0], arg0, arg1, arg2, arg3);
  871.             if (errno_addr != 0)
  872.               SET_MEM_WORD(errno_addr, errno);
  873.             break;
  874.           }
  875.  
  876.         case SPC_SYSCALL:
  877.           /* These special syscalls need to be simulated by SPIM */
  878.           switch(R[REG_V0])
  879.             {
  880.             case SYS_exit:
  881.               return(0);
  882.               break;
  883.  
  884.             case SYS_sbrk:
  885.               {
  886.             expand_data (R[REG_A0]);
  887.             R[REG_RES] = program_break;
  888.             program_break += R[REG_A0];
  889.             break;
  890.               }
  891.  
  892.             case SYS_brk:
  893.               /* Round up to 4096 byte (page) boundary */
  894.               if (((int) R[REG_A0] - (int) data_top) > 0)
  895.             expand_data (ROUND(R[REG_A0], 4096) - (int) data_top);
  896.               R[REG_RES] = program_break;
  897.               program_break = ROUND (R[REG_A0], 4096);
  898.               break;
  899.  
  900.             default:
  901.               run_error (sprintf(mess_buff,
  902.                 "Unknown special system call: %d\n", R[REG_V0]));
  903.               break;
  904.             }
  905.           break;
  906.  
  907.         default:
  908.           run_error(sprintf(mess_buff,
  909.             "Unknown type for syscall: %d\n", R[REG_V0]));
  910.           break;
  911.         }
  912.         }
  913.       else
  914. #endif
  915.         {
  916.           /* It is a true pleasure to write an operating system in a
  917.          high-level language! */
  918.  
  919.           /* Dummy system calls for SPIMs assembly option */
  920.           switch (R[REG_V0])
  921.         {
  922.         case PRINT_INT_SYSCALL:
  923.           sprintf(mess_buff, "%d", R[REG_A0]);
  924.           write_output (console_out, mess_buff);
  925.           break;
  926.  
  927.         case PRINT_FLOAT_SYSCALL:
  928.           {
  929.             float val = FPR_S (REG_FA0);
  930.  
  931.             sprintf(mess_buff, "%f", val);
  932.             write_output (console_out, mess_buff);
  933.             break;
  934.           }
  935.  
  936.         case PRINT_DOUBLE_SYSCALL:
  937.           sprintf(mess_buff, "%f", FPR[REG_FA0/2]);
  938.           write_output (console_out, mess_buff);
  939.           break;
  940.  
  941.         case PRINT_STRING_SYSCALL:
  942.           sprintf(mess_buff, "%s", MEM_ADDRESS (R[REG_A0]));
  943.           write_output (console_out, mess_buff);
  944.           break;
  945.  
  946.         case PRINT_CHARACTER_SYSCALL:
  947.           sprintf(mess_buff, "%c", R[REG_A0]);
  948.           write_output (console_out, mess_buff);
  949.           break;
  950.  
  951.         case READ_INT_SYSCALL:
  952.           {
  953.             static char str [256];
  954.  
  955.             read_input (str, 256);
  956.             R[REG_RES] = atol (str);
  957.             break;
  958.           }
  959.  
  960.         case READ_FLOAT_SYSCALL:
  961.           {
  962.             static char str [256];
  963.  
  964.             read_input (str, 256);
  965.             FGR [REG_FRES] = (float) atof (str);
  966.             break;
  967.           }
  968.  
  969.         case READ_DOUBLE_SYSCALL:
  970.           {
  971.             static char str [256];
  972.  
  973.             read_input (str, 256);
  974.             FPR [REG_FRES] = atof (str);
  975.             break;
  976.           }
  977.  
  978.         case READ_STRING_SYSCALL:
  979.           {
  980.             read_input ((char *) MEM_ADDRESS (R[REG_A0]), R[REG_A1]);
  981.             break;
  982.           }
  983.  
  984.         case READ_CHARACTER_SYSCALL:
  985.           {
  986.             char str[2];
  987.             
  988.             read_input (str , 2);
  989.             if (*str == '\0') 
  990.               *str = '\n';        /* makes xspim = spim */
  991.             R[REG_V0] = (long)*str;
  992.             break;
  993.           }
  994.  
  995.         case SBRK_SYSCALL:
  996.           {
  997.             mem_addr x = data_top;
  998.             expand_data (R[REG_A0]);
  999.             R[REG_RES] = x;
  1000.             break;
  1001.           }
  1002.  
  1003.         case EXIT_SYSCALL:
  1004.           return (0);
  1005.  
  1006.         default:
  1007.           sprintf(mess_buff, "Unknown system call: %d\n",
  1008.                     R[REG_V0]);
  1009.           run_error (mess_buff);
  1010.           break;
  1011.         }
  1012.         }
  1013.        break;
  1014.  
  1015.     case Y_TLBP_OP:
  1016.     case Y_TLBR_OP:
  1017.     case Y_TLBWI_OP:
  1018.     case Y_TLBWR_OP:
  1019.       fatal_error ("Unimplemented operation\n");
  1020.       break;
  1021.  
  1022.     case Y_XOR_OP:
  1023.       R[RD (inst)] = R[RS (inst)] ^ R[RT (inst)];
  1024.       break;
  1025.  
  1026.     case Y_XORI_OP:
  1027.       R[RT (inst)] = R[RS (inst)] ^ (0xffff & IMM (inst));
  1028.       break;
  1029.  
  1030.  
  1031.       /* FPA Operations */
  1032.  
  1033.  
  1034.     case Y_ABS_S_OP:
  1035.       SET_FPR_S (FD (inst), fabs (FPR_S (FS (inst))));
  1036.       break;
  1037.  
  1038.     case Y_ABS_D_OP:
  1039.       SET_FPR_D (FD (inst), fabs (FPR_D (FS (inst))));
  1040.       break;
  1041.  
  1042.     case Y_ADD_S_OP:
  1043.       SET_FPR_S (FD (inst), FPR_S (FS (inst)) + FPR_S (FT (inst)));
  1044.       /* Should trap on inexact/overflow/underflow */
  1045.       break;
  1046.  
  1047.     case Y_ADD_D_OP:
  1048.       SET_FPR_D (FD (inst), FPR_D (FS (inst)) + FPR_D (FT (inst)));
  1049.       /* Should trap on inexact/overflow/underflow */
  1050.       break;
  1051.  
  1052.     case Y_BC1F_OP:
  1053.       BRANCH_INST (FpCond == 0, PC + (SIGN_EX (IOFFSET (inst)) << 2));
  1054.       break;
  1055.  
  1056.     case Y_BC1T_OP:
  1057.       BRANCH_INST (FpCond == 1, PC + (SIGN_EX (IOFFSET (inst)) << 2));
  1058.       break;
  1059.  
  1060.     case Y_C_F_S_OP:
  1061.     case Y_C_UN_S_OP:
  1062.     case Y_C_EQ_S_OP:
  1063.     case Y_C_UEQ_S_OP:
  1064.     case Y_C_OLE_S_OP:
  1065.     case Y_C_ULE_S_OP:
  1066.     case Y_C_SF_S_OP:
  1067.     case Y_C_NGLE_S_OP:
  1068.     case Y_C_SEQ_S_OP:
  1069.     case Y_C_NGL_S_OP:
  1070.     case Y_C_LT_S_OP:
  1071.     case Y_C_NGE_S_OP:
  1072.     case Y_C_LE_S_OP:
  1073.     case Y_C_NGT_S_OP:
  1074.       {
  1075.         float v1 = FPR_S (FS (inst)), v2 = FPR_S (FT (inst));
  1076.         double dv1 = v1, dv2 = v2;
  1077.         int less, equal, unordered;
  1078.         int cond = COND (inst);
  1079.  
  1080.         if (NaN (dv1) || NaN (dv2))
  1081.           {
  1082.         less = 0;
  1083.         equal = 0;
  1084.         unordered = 1;
  1085.         if (cond & COND_IN)
  1086.           RAISE_EXCEPTION (INVALID_EXCEPT, break);
  1087.           }
  1088.         else
  1089.           {
  1090.         less = v1 < v2;
  1091.         equal = v1 == v2;
  1092.         unordered = 0;
  1093.           }
  1094.         FpCond = 0;
  1095.         if (cond & COND_LT)
  1096.           FpCond |= less;
  1097.         if (cond & COND_EQ)
  1098.           FpCond |= equal;
  1099.         if (cond & COND_UN)
  1100.           FpCond |= unordered;
  1101.       }
  1102.       break;
  1103.  
  1104.     case Y_C_F_D_OP:
  1105.     case Y_C_UN_D_OP:
  1106.     case Y_C_EQ_D_OP:
  1107.     case Y_C_UEQ_D_OP:
  1108.     case Y_C_OLE_D_OP:
  1109.     case Y_C_ULE_D_OP:
  1110.     case Y_C_SF_D_OP:
  1111.     case Y_C_NGLE_D_OP:
  1112.     case Y_C_SEQ_D_OP:
  1113.     case Y_C_NGL_D_OP:
  1114.     case Y_C_LT_D_OP:
  1115.     case Y_C_NGE_D_OP:
  1116.     case Y_C_LE_D_OP:
  1117.     case Y_C_NGT_D_OP:
  1118.       {
  1119.         double v1 = FPR_D (FS (inst)), v2 = FPR_D (FT (inst));
  1120.         int less, equal, unordered;
  1121.         int cond = COND (inst);
  1122.  
  1123.         if (NaN (v1) || NaN (v2))
  1124.           {
  1125.         less = 0;
  1126.         equal = 0;
  1127.         unordered = 1;
  1128.         if (cond & COND_IN)
  1129.           RAISE_EXCEPTION (INVALID_EXCEPT, break);
  1130.           }
  1131.         else
  1132.           {
  1133.         less = v1 < v2;
  1134.         equal = v1 == v2;
  1135.         unordered = 0;
  1136.           }
  1137.         FpCond = 0;
  1138.         if (cond & COND_LT)
  1139.           FpCond |= less;
  1140.         if (cond & COND_EQ)
  1141.           FpCond |= equal;
  1142.         if (cond & COND_UN)
  1143.           FpCond |= unordered;
  1144.       }
  1145.       break;
  1146.  
  1147.     case Y_CFC1_OP:
  1148.       R[RT (inst)] = FCR[RD (inst)]; /* RD not FS */
  1149.       break;
  1150.  
  1151.     case Y_CTC1_OP:
  1152.       FCR[RD (inst)] = R[RT (inst)]; /* RD not FS */
  1153.       break;
  1154.  
  1155.     case Y_CVT_D_S_OP:
  1156.       {
  1157.         double val = FPR_S (FS (inst));
  1158.  
  1159.         SET_FPR_D (FD (inst), val);
  1160.         break;
  1161.       }
  1162.  
  1163.     case Y_CVT_D_W_OP:
  1164.       {
  1165.         double val = FPR_W (FS (inst));
  1166.  
  1167.         SET_FPR_D (FD (inst), val);
  1168.         break;
  1169.       }
  1170.  
  1171.     case Y_CVT_S_D_OP:
  1172.       {
  1173.         float val = FPR_D (FS (inst));
  1174.  
  1175.         SET_FPR_S (FD (inst), val);
  1176.         break;
  1177.       }
  1178.  
  1179.     case Y_CVT_S_W_OP:
  1180.       {
  1181.         float val = FPR_W (FS (inst));
  1182.  
  1183.         SET_FPR_S (FD (inst), val);
  1184.         break;
  1185.       }
  1186.  
  1187.     case Y_CVT_W_D_OP:
  1188.       {
  1189.         int val = FPR_D (FS (inst));
  1190.  
  1191.         SET_FPR_W (FD (inst), val);
  1192.         break;
  1193.       }
  1194.  
  1195.     case Y_CVT_W_S_OP:
  1196.       {
  1197.         int val = FPR_S (FS (inst));
  1198.  
  1199.         SET_FPR_W (FD (inst), val);
  1200.         break;
  1201.       }
  1202.  
  1203.     case Y_DIV_S_OP:
  1204.       SET_FPR_S (FD (inst), FPR_S (FS (inst)) / FPR_S (FT (inst)));
  1205.       break;
  1206.  
  1207.     case Y_DIV_D_OP:
  1208.       SET_FPR_D (FD (inst), FPR_D (FS (inst)) / FPR_D (FT (inst)));
  1209.       break;
  1210.  
  1211.     case Y_LWC1_OP:
  1212.       {
  1213.         reg_word *wp = (reg_word *) &FGR [FT (inst)];
  1214.  
  1215.         LOAD_INST (READ_MEM_WORD, R[BASE (inst)] + IOFFSET (inst), wp,
  1216.                0xffffffff);
  1217.         break;
  1218.       }
  1219.  
  1220.     case Y_MFC1_OP:
  1221.       {
  1222.         float val = FGR [RD (inst)]; /* RD not FS */
  1223.         reg_word *vp = (reg_word *) &val;
  1224.  
  1225.         R[RT (inst)] = *vp;    /* Fool coercion */
  1226.         break;
  1227.       }
  1228.  
  1229.     case Y_MOV_S_OP:
  1230.       SET_FPR_S (FD (inst), FPR_S (FS (inst)));
  1231.       break;
  1232.  
  1233.     case Y_MOV_D_OP:
  1234.       SET_FPR_D (FD (inst), FPR_D (FS (inst)));
  1235.       break;
  1236.  
  1237.     case Y_MTC1_OP:
  1238.       {
  1239.         reg_word word = R[RT (inst)];
  1240.         float *wp = (float *) &word;
  1241.  
  1242.         FGR [RD (inst)] = *wp; /* RD not FS, fool coercion */
  1243.         break;
  1244.       }
  1245.  
  1246.     case Y_MUL_S_OP:
  1247.       SET_FPR_S (FD (inst), FPR_S (FS (inst)) * FPR_S (FT (inst)));
  1248.       break;
  1249.  
  1250.     case Y_MUL_D_OP:
  1251.       SET_FPR_D (FD (inst), FPR_D (FS (inst)) * FPR_D (FT (inst)));
  1252.       break;
  1253.  
  1254.     case Y_NEG_S_OP:
  1255.       SET_FPR_S (FD (inst), -FPR_S (FS (inst)));
  1256.       break;
  1257.  
  1258.     case Y_NEG_D_OP:
  1259.       SET_FPR_D (FD (inst), -FPR_D (FS (inst)));
  1260.       break;
  1261.  
  1262.     case Y_SUB_S_OP:
  1263.       SET_FPR_S (FD (inst), FPR_S (FS (inst)) - FPR_S (FT (inst)));
  1264.       break;
  1265.  
  1266.     case Y_SUB_D_OP:
  1267.       SET_FPR_D (FD (inst), FPR_D (FS (inst)) - FPR_D (FT (inst)));
  1268.       break;
  1269.  
  1270.     case Y_SWC1_OP:
  1271.       {
  1272.         float val = FGR [RT (inst)];
  1273.         reg_word *vp = (reg_word *) &val;
  1274.  
  1275.         SET_MEM_WORD (R[BASE (inst)] + IOFFSET (inst), *vp);
  1276.         break;
  1277.       }
  1278.     default:
  1279.       sprintf(mess_buff, "Unknown instruction type: %d\n",
  1280.             OPCODE (inst));
  1281.       fatal_error (mess_buff);
  1282.       break;
  1283.     }
  1284.  
  1285.       PC += BYTES_PER_WORD;
  1286.  
  1287.       if (exception_occurred && ((Cause >> 2) > LAST_REAL_EXCEPT))
  1288.     EPC = PC - BYTES_PER_WORD;
  1289.  
  1290.       if (exception_occurred && !quiet)
  1291.     {
  1292.       sprintf(mess_buff, "Exception occurred at PC=0x%08x\n", EPC);
  1293.       error (mess_buff);
  1294.  
  1295.       switch (Cause >> 2)
  1296.         {
  1297.         case INT_EXCPT:
  1298.           error ("  Interrupt exception");
  1299.           break;
  1300.  
  1301.         case ADDRL_EXCPT:
  1302.           sprintf(mess_buff,
  1303.                 "  Unaligned address in inst/data fetch: 0x%08x\n",
  1304.                 BadVAddr);
  1305.           error (mess_buff);
  1306.           break;
  1307.  
  1308.         case ADDRS_EXCPT:
  1309.           sprintf(mess_buff, "  Unaligned address in store: 0x%08x\n",
  1310.                 BadVAddr);
  1311.           error (mess_buff);
  1312.           break;
  1313.  
  1314.         case IBUS_EXCPT:
  1315.           sprintf(mess_buff, "  Bad address in text read: 0x%08x\n",
  1316.                 BadVAddr);
  1317.           error (mess_buff);
  1318.           break;
  1319.  
  1320.         case DBUS_EXCPT:
  1321.           sprintf(mess_buff,
  1322.                 "  Bad address in data/stack read: 0x%08x\n", BadVAddr);
  1323.           error (mess_buff);
  1324.           break;
  1325.  
  1326.         case BKPT_EXCPT:
  1327.           break;
  1328.  
  1329.         case SYSCALL_EXCPT:
  1330.           error ("  Error in syscall");
  1331.           break;
  1332.  
  1333.         case RI_EXCPT:
  1334.           error ("  Reserved instruction execution");
  1335.           break;
  1336.  
  1337.         case OVF_EXCPT:
  1338.           error ("  Arithmetic overflow");
  1339.           break;
  1340.  
  1341.             case CLOCK_EXCPT:
  1342.               error ("  Clock interrupt\n");
  1343.               break;
  1344.  
  1345.             case IO_EXCPT:
  1346.               error ("  IO interrupt\n");
  1347.               break;
  1348.  
  1349.         default:
  1350.           sprintf(mess_buff, "Unknown exception: %d\n", Cause >> 2);
  1351.           error (mess_buff);
  1352.           break;
  1353.         }
  1354.       exception_occurred = 0;
  1355.       PC = EXCEPTION_ADDR;
  1356.     }
  1357.     }                /* End of while */
  1358.  
  1359.   /* Executed enought steps, return, but are able to continue. */
  1360.   return (1);
  1361. }
  1362.  
  1363. /* Multiply two 32-bit numbers, V1 and V2, to produce a 64 bit result in
  1364.    the HI/LO registers.     The algorithm is high-school math:
  1365.  
  1366.      A B
  1367.        x C D
  1368.        ------
  1369.        AD || BD
  1370.  AC || CB || 0
  1371.  
  1372.  where A and B are the high and low short words of V1, C and D are the short
  1373.  words of V2, AD is the product of A and D, and X || Y is (X << 16) + Y.
  1374.  Since the algorithm is programmed in C, we need to be careful not to
  1375.  overflow. */
  1376.  
  1377. static void long_multiply (reg_word v1, reg_word v2)
  1378. {
  1379.   register long a, b, c, d;
  1380.   register long x, y;
  1381.  
  1382.   a = (v1 >> 16) & 0xffff;
  1383.   b = v1 & 0xffff;
  1384.   c = (v2 >> 16) & 0xffff;
  1385.   d = v2 & 0xffff;
  1386.  
  1387.   LO = b * d;            /* BD */
  1388.   x = a * d + c * b;        /* AD + CB */
  1389.   y = ((LO >> 16) & 0xffff) + x;
  1390.  
  1391.   LO = (LO & 0xffff) | ((y & 0xffff) << 16);
  1392.   HI = (y >> 16) & 0xffff;
  1393.  
  1394.   HI += a * c;            /* AC */
  1395. }
  1396.